#include <iostream>

#include <vector>
#include <type_traits>
#include <functional>
#include <map>




/*
    左值右值
    从c++17开始，
    返回一个与返回值类型相同地纯右值，强制省略拷贝
*/

// void set_val(int val)
// {
//     int x = *&val; //val 是个左值，生命周期是整个函数

//     int&& k = std::move(val);
    
//     &k;//右值引用也是变量，可以取地址就是左值
// }

class X
{
public:
    X()
    {
        std::cout << "X()" << std::endl;
    }

    ~X()
    {
        // std::cout << "~X()" << std::endl;
    }   

    //如果不加const
    X(const X& x)
    {
        std::cout << "X(const X& x)" << std::endl;
    }

    //移动构造函数最好不要抛出异常
    //避免出现两部分都不完整的情况
    X(X&& x) noexcept
    {
        std::cout << "X(X&& x)" <<std::endl;
    }

    int val_=10;
};

X make_x()
{
    //没有合适的拷贝构造
    //因为X()出来后是个右值
    //但在c++17后不会报错，因为编译器会再做一次优化
    //将拷贝尽可能地优化掉

    //过程：
    //先调用构造函数，生成了一个 纯右值 ，现在要返回这个纯右值
    //如果有移动构造，先使用移动构造 X(X&& x) noexcept
    //没有的话，使用拷贝构造（也可以接受右值const引用）X(const X& x)
    return X();
}

void move_x(X&& x)
{
    std::cout <<"call move_x"<<std::endl;

    //但是这里的x本身还是个左值,所以就要将x转为右值，让他能走移动构造的逻辑
    //因为没有必要再去拷贝构造一次
    // X tem(std::move(x));

    // X tem(static_cast<X&&>(x));


}

int main()
{   

    move_x(make_x());


    // X x1;
    // X x2 = x1;
    // X x3 = static_cast<X&&>(x1);//x1是左值,强转为右值，也是将亡值（是临时的，也占内存）
    //但从语法来说，x1仍然可以用

    // make_x();
    // X&& x1 = make_x();//
    // std::cout << std::endl;


    // int a = make_x().val_;
    // X x2 = make_x();

    // int i;
    // //&i++; //报错，i++返回的是一个将亡值，是右值
    // &++i;
    // std::cout << i << std::endl;

    // set_val(8);//8是右值

    // &"hello world";//字符串常量也是左值，字符串字面量的地址我们是可以拿到的

    // const int & a1 = 1;//a1的生命周期演唱
    // const int   a2 = 1;//右值1被销毁，去到了变量a2里面
}



/*
包装
*/

// void init_internet(std::string host,int port)
// {
//     std::cout << "init_internet " << host << " " << port << std::endl;
// }


// void init_sql(int id)
// {
//     std::cout << "init_sql" << std::endl;
// }


// //统一调度函数
// template<typename Func,typename ...Args>
// void execute(Func func,Args... args)
// {
//     func(args...);
// }

// int main()
// {
//     //编译器会自动推导类型
//     // execute<init_internet>(init_internet,"127.0.0.1",9090);
//     execute(init_sql,110);

//     return 0;
// }


// class Sub
// {
// public:
//     int func(int a, int b)
//     {
//         return a - b;
//     }
// };

// int main()
// {
//     Sub sub;

//     std::function<int(Sub, int, int)> f1 = (&Sub::func);
//     std::function<int(int, int)> f2 = std::bind(&Sub::func, &sub,
//                                                 std::placeholders::_1, std::placeholders::_2);

//     std::cout << f1(sub,1,2) << std::endl;
//     std::cout << f2(1,2) << std::endl;
//     return 0;
// }

/*
4、lambda表达式 包装器
*/

// class Sub
// {
// public:
//     int operator()(int a,int b)
//     {
//         return a-b;
//     }

//     int operator+(int a)
//     {
//         return a;
//     }
// };

// typedef int(*fp)(int, int);

// int add(int a,int b)
// {
//     return a+b;
// }

// int main()
// {
//     Sub sub;
//     // std::cout << sub+(1) << std::endl;
//     std::cout << sub(1,2) << std::endl;

//     fp f = add;
//     std::cout << f(1,2) << std::endl;

//     auto sum = [](int a,int b) -> int
//     {
//         return a + b;
//     };

//     std::cout << sum(2,3) << std::endl;

// std::map<std::string,std::function<int(int,int)>> operation_map
//     {
//         {"+",add},
//         {"-",sub}
//     };

//     std::cout << "operation_map" << std::endl;
//     std::cout << operation_map["+"](1,2) << std::endl;
//     std::cout << operation_map["-"](1,2) << std::endl;

//     return 0;
// }

/*
3、平凡类型
*/
// class A
// {
// public:
//     A(int val):val_(val)
//     {
//         std::cout << "A()" << std::endl;
//     }
//     ~A() = default;

//     // 拷贝构造
//     A(const A &a)
//     {
//         this->val_ = a.val_;
//         std::cout << "A(const A& a)" << std::endl;
//     }

//     // 赋值重载
//     A &operator=(const A &a)
//     {
//         std::cout << "A operator=(const A& a)" << std::endl;
//         this->val_ = a.val_;
//         return *this;
//     }

//     // 移动构造
//     A(A &&a)
//     {
//         this->val_ = a.val_;
//         std::cout << "A(A &&a)" << std::endl;
//     }

//     //移动赋值
//     A& operator=(A&& a)
//     {
//         this->val_ = a.val_;
//         std::cout << "A& operator=(A&& a)" << std::endl;
//         return *this;
//     }
// private:
//     int val_;
// };

// int func2(const int &a)
// {
//     std::cout << a << std::endl;
// }

// int func()
// {
//     return 10;
// }

// int main()
// {
//     A a1(1),a2(2);
//     a1 = std::move(a2);

//     // std::cout << std::is_trivial<A>::value << std::endl; // 对于int类型，输出为true

//     // A a1, a2, a3;
//     // a3.val_ = 1;

//     // a1 = a2 = a3;

//     // std::cout << a1.val_ << " " << a2.val_ << " " << a3.val_ << std::endl;

//     // int& b = func();
//     // const int& b  = func();
//     // std::cout << b << std::endl;

//     // int a = 9;
//     // func2(a);
//     // func2(func());

//     return 0;
// }

/*
2、指定初始化
*/

// c++20支持，且必须按照定义顺序进行初始化

/*
1、列表初始化
*/

// 当使用列表初始化时 {5,5} 会优先调用列表初始化
// 而(5,5)则调用普通初始化
// struct Time
// {
//     int year;
//     int month;
//     int day;
// };

// class DateTime
// {
// public:
//     // 构造函数
//     DateTime(int year, int month, int day)
//         : year_(year), month_(month), day_(day)
//     {
//     }

//     DateTime(std::initializer_list<Time> il)
//     {
//         std::cout << "DateTime(std::initializer_list<Time> il)" << std::endl;
//     }

//     void getDate()
//     {
//         std::cout << year_ << " " << month_ << " " << day_ << std::endl;
//     }

// private:
//     int year_ = 0;
//     int month_ = 0;
//     int day_ = 0;
// };

// int main()
// {
//     DateTime dt{{1,1,1},{2,2,2}};

//     // std::vector<int> v1 = {1,2,3,4,5};
//     // std::vector<int> v2{1,2,3,4,5};

//     // C c1 = {4};         //复制列表初始化 先调用构造生成临时拷贝，再把拷贝给x1，编译器优化合并了这个过程
//     // C c2{41};
//     // C c3(42);
//     // cout << c1.a << endl;
//     // C c4{{"hello","world","nice","to","meet","you"}};//先调用vector的构造再调用C的构造
//     // cout << c4.strs[1];
//     // C c5{"nihao","woshi","xiaoming"};

//     // int a = {0};
//     // int b{0};
//     // int arr[]{1, 2, 3, 4, 5, 6};

//     // for(auto e : arr){cout<<e<<endl;}

//     // DateTime date{2024,1,14};
//     // date.getDate();
// }

// struct C
// {
//     C(std::initializer_list<std::string> a)
//     {
//         std::cout << "    C(std::initializer_list<std::string> a)" << std::endl;
//         for(const std::string* item = a.begin();item != a.end();++item)
//         {
//             std::cout << std::hex << item << " ";
//         }
//         std::cout << std::endl;
//         std::cout << "sizeof(std::string)" << sizeof(std::string) << std::endl;
//     }

//     C(std::vector<std::string> v)
//         : strs(v)
//     {}

//     C(std::string a, int b) {}

//     //标记为explicit的构造函数不允许隐式转换
//     explicit C(int a)
//     {
//         std::cout << a;
//         std::cout << " C(int a)" <<std::endl;
//     }

//     int a;
//     std::vector<std::string> strs;
// };
